#include "Input.h"
#include <SPI.h>
#include <RF24.h>
#include <nRF24L01.h>
#include "StarburstCommon.h"
#include <EEPROM.h>
#include "Transmitter.h"
#include "FFTDisp.h"
#define LEDLIB_GRB_ORDER  1       // GRB leds
#include "LEDFx.h"
#include <FHT.h>


//#define SHOW_LEDS
#ifdef SHOW_LEDS
#define LED_PIN           2
//-- LED Options
#define SHIFT_RATE        0.0001  // rate of LED color change in hue degrees/360 per refresh
CRGB* cBuffer;
float                     colorShift = 0;
#else
Transmitter transmitter(9,10);
#endif

#ifndef PRINT_DEBUG
#define CALLIBRATE_PIN    1       // the input value controlling calibration
#endif
//-- Program constants
LegData data[16];

Mode currentMode = Rainbow;
unsigned long lastModeChange;


void readHVL();
void enableSoundMode();
void enableSolidMode();
void displayMode(Mode m);
int serial_putc( char c, FILE * );


void setup() {
#ifdef PRINT_DEBUG
  Serial.begin(115200);
  delay(1000);
#endif

  fdevopen( &serial_putc, 0 );
#ifdef SHOW_LEDS
	// setup the light strip. 
	FastSPI_LED.setLeds(LED_COUNT);
	FastSPI_LED.setPin(LED_PIN);
	FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2811);  
	FastSPI_LED.init();
	FastSPI_LED.start();
  cBuffer = (CRGB*)FastSPI_LED.getRGBData();
  memset(cBuffer,128,LED_COUNT * sizeof(CRGB));
  FastSPI_LED.show();
#else
  transmitter.init();
  // we start in sound mode. Init takes some time. display the loading animation while we wait.
  transmitter.setLoadingMode(0,255,0);
#endif
  pinMode(CALLIBRATE_PIN, INPUT_PULLUP);
  pinMode(LINE_IN_PIN, INPUT_PULLUP);
  initInputs();
  initDisp();
  displayMode(currentMode);
};



void loop() {
	static bool lastClipped = false;
	static uint32_t blinkTime;
#ifndef PRINT_DEBUG
    if(digitalRead(CALLIBRATE_PIN) == LOW) {
      transmitter.setLoadingMode(255,0,0);
      calibrate();
      displayMode(currentMode);
   }
#endif
   if(update(currentMode)) {
     displayMode(currentMode);
   }
#ifdef SHOW_LEDS
      colorShift += SHIFT_RATE;
      if(colorShift >= 1.0)
        colorShift -= 1.0;
#endif
   if(currentMode == Sound) {
	   // if it clipped, turn off the leds
    if(displayFFT(data)) {
		if(!lastClipped) {
			blinkTime = millis();
			updateKnobs(EMPTY_COLOR);
			lastClipped = true;
		}
    }
	else {
		if(lastClipped && (millis() - blinkTime) > 100) {
			updateKnobs();
			lastClipped = false;
		}
	}
#ifdef SHOW_LEDS
      drawAudioData(data,cBuffer,colorShift,saturation,2,value);
#else
	transmitter.sendLegData(data, OCTAVES);
#endif
  }

  // otherwise, just refresh the current mode
  else {
      displayMode(currentMode);
  }
};



void enableSoundMode() {
#ifndef SHOW_LEDS
  transmitter.setAudioMode(10,value,saturation);
#endif
}

void enableWaveMode() {
#ifndef SHOW_LEDS
  transmitter.setLightMode(Wave, hue,saturation,value);
#endif
}



void enableSolidMode() {
#ifdef SHOW_LEDS
  float h = ((float)hue)/256.0 + colorShift;
  if(h > 1.0) 
    h -= 1.0;
  CRGB color = LEDFxUtilities::HSVtoRGB(h*255,saturation,value);
  updateKnobs(color);
  for(int i = 0; i < LED_COUNT; i++) {
    cBuffer[i] = color;
  }
  FastSPI_LED.show();
#else
   transmitter.setConstantColorMode(hue,saturation,value);
#endif
}
void displayMode(Mode m) {
  switch(m) {
  case Wave:
    enableWaveMode();
    break;
  case Sound:
    enableSoundMode();
    break;
  case Solid:
    enableSolidMode();
    break;
  case Rainbow:
	  transmitter.setLightMode(Rainbow, hue,saturation,value);
  }
  currentMode = m;
}
int serial_putc( char c, FILE * ) 
{
  Serial.write( c );

  return c;
} 
